package com.xjscrm.console.service.customer.circle;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xjscrm.common.annotation.MerId;
import com.xjscrm.common.entity.WwDevice;
import com.xjscrm.common.entity.WwTags;
import com.xjscrm.common.exception.BusinessException;
import com.xjscrm.console.dto.circle.CircleTaskDTO;
import com.xjscrm.console.dto.circle.CircleTaskMqDTO;
import com.xjscrm.console.dto.circle.CircleTaskSearchDTO;
import com.xjscrm.console.dto.circle.CircleVisibleDTO;
import com.xjscrm.console.entity.CircleTask;
import com.xjscrm.console.entity.CircleTaskPublish;
import com.xjscrm.console.mapper.CircleTaskMapper;
import com.xjscrm.console.mapper.CircleTaskPublishMapper;
import com.xjscrm.console.mapper.WwDeviceMapper;
import com.xjscrm.console.mapper.WwTagsMapper;
import com.xjscrm.console.queue.DelayProducer;
import com.xjscrm.console.queue.DelayTask;
import com.xjscrm.console.vo.CircleTaskVO;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.xjscrm.console.mq.consumer.PullCircleTaskMessageConsumer.sendCircleTask;

/**
 * @author mingyang.chen create in 2024/4/9 上午10:26
 */
@Service
public class CircleTaskService {

    @Autowired
    private CircleTaskMapper circleTaskMapper;
    @Autowired
    private CircleTaskPublishMapper circleTaskPublishMapper;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private WwDeviceMapper wwDeviceMapper;
    @Autowired
    private WwTagsMapper wwTagsMapper;


    public int deleteByPrimaryKey(Long id) {
        return circleTaskMapper.deleteByPrimaryKey(id);
    }


    public int insertSelective(CircleTask record) {
        return circleTaskMapper.insertSelective(record);
    }


    public CircleTask selectByPrimaryKey(Long id) {
        return circleTaskMapper.selectByPrimaryKey(id);
    }


    public int updateByPrimaryKeySelective(CircleTask record) {
        return circleTaskMapper.updateByPrimaryKeySelective(record);
    }

    public Object page(@MerId Long merId, CircleTaskSearchDTO source) {

        Page<CircleTask> page = new Page<>(source.getCurrent(), source.getSize());
        source.convert(page);
        List<CircleTask> circleTaskList = circleTaskMapper.selectPage(page, source);

        List<CircleTaskVO> resultRecord = new ArrayList<>();
        for (CircleTask circleTask : circleTaskList) {
            resultRecord.add(
                    this.convert(circleTask)
            );
        }
        return new Page<CircleTaskVO>(page.getCurrent(), page.getSize(), page.getTotal()).setRecords(resultRecord);
    }

    public CircleTaskVO get(@MerId Long merId, Long taskId) {
        CircleTask circleTask = circleTaskMapper.selectByPrimaryKey(taskId);
        if (Objects.isNull(circleTask)) {
            throw new BusinessException("朋友圈任务不存在");
        }
        return this.convert(circleTask);
    }

    public CircleTaskVO convert(CircleTask circleTask) {
        Long merId = circleTask.getMerId();
        Long taskId = circleTask.getId();

        CircleTaskVO circleTaskVO = new CircleTaskVO();

        BeanUtils.copyProperties(circleTask, circleTaskVO);
        // 发布集合
        this.fillDeviceUniqueIds(merId, taskId, circleTaskVO);

        if (StringUtils.isNoneBlank(circleTask.getComments())) {
            circleTaskVO.setComments(JSON.parseArray(circleTask.getComments(), String.class));
        }
        if (StringUtils.isNoneBlank(circleTask.getImgs())) {
            circleTaskVO.setImgs(JSON.parseArray(circleTask.getImgs(), String.class));
        }
        if (StringUtils.isNoneBlank(circleTask.getVisibleCondition())) {
            circleTaskVO.setVisibleCondition(JSON.parseObject(circleTask.getVisibleCondition(), CircleVisibleDTO.class));
        }
        if (StringUtils.isNoneBlank(circleTask.getVisibleTags())) {
            List<Long> longs = JSON.parseArray(circleTask.getVisibleTags(), Long.class);
            List<WwTags> wwTags = wwTagsMapper.selectListByIds(merId, longs);
            wwTags.forEach(item -> circleTaskVO.addTag(item.getId(), item.getTagName()));
        }
        return circleTaskVO;
    }

    public CircleTask getById(@MerId Long merId, Long taskId) {
        CircleTask circleTask = circleTaskMapper.selectByPrimaryKey(taskId);
        if (Objects.isNull(circleTask)) {
            throw new BusinessException("朋友圈任务不存在");
        }
        return circleTask;
    }

    public void fillDeviceUniqueIds(@MerId Long merId, Long taskId, CircleTaskVO circleTaskVO) {
        List<CircleTaskPublish> circleTaskPublishes = circleTaskPublishMapper.selectListByTaskId(merId, taskId);
        if (ObjectUtils.isNotEmpty(circleTaskPublishes)) {
            List<Long> deviceUniqueIds = circleTaskPublishes.stream().map(CircleTaskPublish::getDeviceUniqueId).distinct().collect(Collectors.toList());
            circleTaskVO.setDeviceUniqueIds(deviceUniqueIds);
            List<WwDevice> wwDevices = wwDeviceMapper.selectByIds(merId, deviceUniqueIds);
            wwDevices.forEach(item -> circleTaskVO.addDevice(item.getId(), item.getDeviceName()));
        }
    }

    @Transactional
    public Object add(@MerId Long merId, Long staffId, CircleTaskDTO source) {

        CircleTask circleTask = new CircleTask();
        BeanUtils.copyProperties(source, circleTask);
        circleTask.setId(IdUtil.getSnowflakeNextId());
        circleTask.setMerId(merId);
        circleTask.setStaffId(staffId);
        circleTask.setStatus(20);
        circleTask.setCreateTime((int) (System.currentTimeMillis() / 1000L));
        circleTask.setUpdateTime((int) (System.currentTimeMillis() / 1000L));
        circleTask.setExecuteTime(source.getExecuteTime());
        if (ObjectUtils.isNotEmpty(source.getVisibleTags())) {
            circleTask.setVisibleTags(JSON.toJSONString(source.getVisibleTags()));
        }
        if (ObjectUtils.isNotEmpty(source.getImgs())) {
            circleTask.setImgs(JSON.toJSONString(source.getImgs()));
        }
        if (ObjectUtils.isNotEmpty(source.getComments())) {
            circleTask.setComments(JSON.toJSONString(source.getComments()));
        }
        if (Objects.equals(source.getDelay(), 0)) {
            circleTask.setExecuteTime((int) (System.currentTimeMillis() / 1000L));
        }

        circleTaskMapper.insertSelective(circleTask);

        for (Long deviceUniqueId : source.getDeviceUniqueIds()) {
            CircleTaskPublish circleTaskPublish = new CircleTaskPublish();

            circleTaskPublish.setId(IdUtil.getSnowflakeNextId());
            circleTaskPublish.setDeviceUniqueId(deviceUniqueId);
            circleTaskPublish.setMerId(merId);
            circleTaskPublish.setStaffId(staffId);
            circleTaskPublish.setTaskId(circleTask.getId());
            circleTaskPublish.setPublishTime(circleTask.getExecuteTime());
            circleTaskPublish.setStatus(30);
            circleTaskPublish.setCreateTime((int) (System.currentTimeMillis() / 1000L));
            circleTaskPublish.setUpdateTime((int) (System.currentTimeMillis() / 1000L));
            circleTaskPublishMapper.insertSelective(circleTaskPublish);
        }

        CircleTaskMqDTO circleTaskMqDTO = new CircleTaskMqDTO();
        circleTaskMqDTO.setMerId(circleTask.getMerId());
        circleTaskMqDTO.setTaskId(circleTask.getId());

        if (Objects.equals(source.getDelay(), 0)) {
            sendCircleTask(rocketMQTemplate, circleTaskMqDTO).run();
        } else {
            Integer current = (int) (System.currentTimeMillis() / 1000L);
            DelayTask delayTask = new DelayTask(merId, circleTask.getId(), circleTask.getName(), circleTask.getExecuteTime().longValue() - current.longValue(), sendCircleTask(rocketMQTemplate, circleTaskMqDTO));
            DelayProducer.instance.addSendDelayTask(delayTask);
        }

        return true;
    }

    public Object cancel(@MerId Long merId, Long id) {

        CircleTask circleTask = circleTaskMapper.selectByPrimaryKey(id);

        if (Objects.isNull(circleTask)) {
            throw new BusinessException("朋友圈任务未找到");
        }
        if (!Objects.equals(circleTask.getStatus(), 20)) {
            throw new BusinessException("朋友圈任务状态, 不支持取消");
        }
        CircleTask update = new CircleTask();
        update.setId(circleTask.getId());
        update.setStatus(23);
        update.setUpdateTime((int) (System.currentTimeMillis() / 1000L));
        circleTaskMapper.updateByPrimaryKeySelective(update);

        //
        DelayTask delayTask = new DelayTask(merId, circleTask.getId(), circleTask.getName(), -1L, () -> {
        });
        DelayProducer.instance.removeSendTask(delayTask);
        return true;
    }

    public Object edit(@MerId Long merId, Long staffId, CircleTaskDTO source) {
        //
        CircleTask circleTask = circleTaskMapper.selectByPrimaryKey(source.getId());
        if (Objects.isNull(circleTask)) {
            throw new BusinessException("朋友圈任务未找到");
        }
        circleTask.setVideos(source.getVideos());
        if (StringUtils.isNoneBlank(source.getName())) {
            circleTask.setName(source.getName());
        }
        if (StringUtils.isNoneBlank(source.getText())) {
            circleTask.setText(source.getText());
        }
        if (ObjectUtils.isNotEmpty(source.getVisibleTags())) {
            circleTask.setVisibleTags(JSON.toJSONString(source.getVisibleTags()));
        }
        if (Objects.nonNull(source.getVisibleCondition())) {
            circleTask.setVisibleCondition(JSON.toJSONString(source.getVisibleCondition()));
        }
        if (ObjectUtils.isNotEmpty(source.getImgs())) {
            circleTask.setImgs(JSON.toJSONString(source.getImgs()));
        }
        if (ObjectUtils.isNotEmpty(source.getComments())) {
            circleTask.setComments(JSON.toJSONString(source.getComments()));
        }

        circleTaskPublishMapper.deleteByTaskId(merId, circleTask.getId());

        for (Long deviceUniqueId : source.getDeviceUniqueIds()) {
            CircleTaskPublish circleTaskPublish = new CircleTaskPublish();

            circleTaskPublish.setId(IdUtil.getSnowflakeNextId());
            circleTaskPublish.setDeviceUniqueId(deviceUniqueId);
            circleTaskPublish.setMerId(merId);
            circleTaskPublish.setStaffId(staffId);
            circleTaskPublish.setTaskId(circleTask.getId());
            circleTaskPublish.setPublishTime(circleTask.getExecuteTime());
            circleTaskPublish.setStatus(30);
            circleTaskPublish.setCreateTime((int) (System.currentTimeMillis() / 1000L));
            circleTaskPublish.setUpdateTime((int) (System.currentTimeMillis() / 1000L));
            circleTaskPublishMapper.insertSelective(circleTaskPublish);
        }
        circleTaskMapper.updateByPrimaryKeySelective(circleTask);
        return true;
    }

    //
    public void executeWithMerId(@MerId Long merId) {

    }

    public List<CircleTask> listValidByMerId(@MerId Long merId) {
        return circleTaskMapper.selectListWithValidByMerId(merId);
    }

    public boolean setTaskStatusIsExecuting(@MerId Long merId, Long taskId) {
        return circleTaskMapper.updateStatusIsExecuting(merId, taskId) > 0;
    }

    public void triggerCompleteTaskIfAbsent(@MerId Long merId, Long taskId) {
        CircleTask circleTask = circleTaskMapper.selectByPrimaryKey(taskId);
        List<CircleTaskPublish> circleTaskPublishes = circleTaskPublishMapper.selectListByTaskId(merId, taskId);
        boolean taskComplete = circleTaskPublishes.stream().allMatch(i -> i.getStatus() != 30);
        if (taskComplete) {
            circleTaskMapper.updateStatusIsComplete(merId, taskId);
        }
        //
        DelayTask delayTask = new DelayTask(merId, circleTask.getId(), "", -1L, () -> {
        });
        DelayProducer.instance.removeSendTask(delayTask);
    }

    public Object remove(@MerId Long merId, Long id) {

        CircleTask circleTask = circleTaskMapper.selectByPrimaryKey(id);
        if (Objects.isNull(circleTask)) {
            throw new BusinessException("朋友圈任务不存在");
        }
        if (!Objects.equals(circleTask.getStatus(), 21)) {
            throw new BusinessException("当前朋友圈任务状态不支持删除");
        }
        circleTaskPublishMapper.deleteByTaskId(merId, id);
        return true;
    }
}
